<?php
namespace app\index\controller;

use think\Db;
use think\facade\Cache;


class Wxpay extends Base
{
    private $mchid = '1518386621';     //微信支付分配的商户号
    private $appid = 'wx87adaba1a2ad81fb';  //微信分配的公众账号ID（企业号corpid即为此appId）
    private $appSecret = '86dd8c1358601f1342b12b8d48dff094';  //公众号开发者密码
    private $key = '08b55be5fa78ae23b57d504f581509f8';  //微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置


    //订单打款
    public function transfers(){
        $openid = 'oscjpw2MGNYeYYe5HgB9vAZPCa38';
        $orderNumber = uniqid();      //订单
        $money = 1;
        $userName = '姓名';             //收款人真实姓名
        $response = $this->transfersQuery($openid,$orderNumber,$money,$userName);
        var_dump($response);  //付款成功才会返回。
    }

    //订单退款
    public function autoRefund(){
        //业务查询
        $order_list= Db::table('tb_order')->where(array("pay_status"=>1,'status'=>2))->limit(10)->select();
        if (!empty($order_list)){
            foreach ($order_list as $item){
                $orderRefundNumber = uniqid();           //商户退款单号
                $orderNumber = $item['order_id'];
                $totalMoney = $item['amount'];
                $refundMoney = $item['amount'];
                // 启动事务
                Db::startTrans();
                try{
                    $response = $this->reFundOrderQuery($orderNumber,$orderRefundNumber,$totalMoney,$refundMoney);
                    Db::table('tb_order')->where('id',$item['id'])->update(array('status'=>3)); //更新订单状态
                    Db::table('tb_order_refund_log')->insert(array(
                            'transaction_id'=>$response['transaction_id'],  //微信订单号
                            'order_refund'=>$response['out_refund_no'],
                            'order_id'=>$response['out_trade_no'],
                            'totalmoney'=>$totalMoney,
                            'refundmoney'=>$response['refund_fee'],
                            'refund_time'=>time(),
                    ));
                    Db::commit();
                    echo 'ok';
                } catch (\Exception $e) {
                    Db::rollback();
                    echo 'no';
                    continue;
                }
            }
        }
    }

    public function transfersQuery($openid,$orderNumber,$money,$userName){
        //$orderName = iconv('GBK','UTF-8',$orderName);
        $data= array(
            'mch_appid' => $this->appid,
            'mchid' => $this->mchid,
            'nonce_str' => self::getNonceStr(),
            'partner_trade_no' => $orderNumber,
            'openid' => $openid,                      //商户appid下，某用户的openid
            'check_name' => 'FORCE_CHECK',
            're_user_name'=>$userName,
            'amount' => intval($money * 100),       //单位 转为分
            'desc' => '付款',         //企业付款备注
        );
        $data['sign'] = self::makeSign($data, $this->key);
        $xml = self::curlPost('	https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers',self::arrayToXml($data));
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $response = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
        if ($response === false) {
            die('parse xml error');
        }
        if ($response->return_code != 'SUCCESS') {
            die($response->return_msg);
        }
        if ($response->result_code != 'SUCCESS') {
            die($response->err_code);
        }
        return (array)$response;
    }

    public function reFundOrderQuery($orderNumber,$orderRefundNumber,$totalMoney,$refundMoney){
        $data= array(
            'appid' => $this->appid,
            'mch_id' => $this->mchid,
            'nonce_str' => self::getNonceStr(),
            'sign_type' => "MD5",
            'out_trade_no' => $orderNumber,
            'out_refund_no' => $orderRefundNumber,
            'total_fee' => intval($totalMoney * 100),
            'refund_fee' => intval($refundMoney * 100),
        );
        $data['sign'] = self::makeSign($data, $this->key);
        $xml = self::curlPost('https://api.mch.weixin.qq.com/secapi/pay/refund',self::arrayToXml($data));
        libxml_disable_entity_loader(true);
        $response = simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
        if ($response === false) {
            die('parse xml error');
        }
        if ($response->return_code != 'SUCCESS') {
            die($response->return_msg);
        }
        if ($response->result_code != 'SUCCESS') {
            die($response->err_code);
        }
        return (array)$response;
    }

    public static function makeSign($arr, $key)
    {
        ksort($arr);
        $string = self::toUrlParams($arr);
        $string = $string . "&key=".$key;
        $string = md5($string);
        $result = strtoupper($string);
        return $result;
    }
    public static function toUrlParams($arr)
    {
        $buff = "";
        foreach ($arr as $k => $v)
        {
            if($k != "sign" && $v != "" && !is_array($v)){
                $buff .= $k . "=" . $v . "&";
            }
        }

        $buff = trim($buff, "&");
        return $buff;
    }
    public static function curlPost($url = '', $data = '', $options = array())
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
        curl_setopt($ch, CURLOPT_TIMEOUT, 30); //设置cURL允许执行的最长秒数
        curl_setopt($ch,CURLOPT_SSLCERT, dirname(dirname(__FILE__)).'/cert/apiclient_cert.pem');
        curl_setopt($ch,CURLOPT_SSLKEY, dirname(dirname(__FILE__)).'/cert/apiclient_key.pem');
        if (!empty($options)) {
            curl_setopt_array($ch, $options);
        }
        if (stripos($url, "https://") !== false) {
            curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        }
        $data = curl_exec($ch);
        curl_close($ch);
        return $data;
    }
    public static function arrayToXml($arr)
    {
        $xml = "<xml>";
        foreach ($arr as $key => $val) {
            if (is_numeric($val)) {
                $xml .= "<" . $key . ">" . $val . "</" . $key . ">";
            } else
                $xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
        }
        $xml .= "</xml>";
        return $xml;
    }
    public static function getNonceStr($length = 32)
    {
        $chars = "abcdefghijklmnopqrstuvwxyz0123456789";
        $str ="";
        for ( $i = 0; $i < $length; $i++ )  {
            $str .= substr($chars, mt_rand(0, strlen($chars)-1), 1);
        }
        return $str;
    }

}
